use crate::ffi::signal_client_t;
use crate::wsclient::WsClient;
use alloc::boxed::Box;
use core::ops::{Deref, DerefMut};
use core::ptr::NonNull;
use embed_std::debugln;

pub struct RSignalClient {
    c: NonNull<signal_client_t>,
    release: bool,
}

impl RSignalClient {
    pub fn new(c: *mut signal_client_t) -> Self {
        Self {
            c: NonNull::new(c).unwrap(),
            release: true,
        }
    }

    pub fn new_ref(c: *mut signal_client_t) -> Self {
        Self {
            c: NonNull::new(c).unwrap(),
            release: false,
        }
    }
}

impl Drop for RSignalClient {
    fn drop(&mut self) {
        if self.release {
            debugln!("drop RSignalClient {:p}", self.c);
            let client = Box::leak(unsafe { Box::from_raw(self.c.as_ptr()) });
            unsafe { client.destroy.unwrap()(self.c.as_ptr()) };
        }
    }
}

impl DerefMut for RSignalClient {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let client = Box::leak(unsafe { Box::from_raw(self.c.as_ptr()) });
        Box::leak(unsafe { Box::from_raw(client.priv_ as *mut WsClient) })
    }
}

impl Deref for RSignalClient {
    type Target = WsClient;

    fn deref(&self) -> &Self::Target {
        let client = Box::leak(unsafe { Box::from_raw(self.c.as_ptr()) });
        Box::leak(unsafe { Box::from_raw(client.priv_ as *mut WsClient) })
    }
}
